package ru.gerunn.etd.parsing;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.hibernate.Query;
import org.hibernate.Session;

import ru.gerunn.parsing.interfaces.ParseHandler;

public class ETDCommonsQueryLoggingListenerParseHandler implements ParseHandler {

	private Pattern pattern = Pattern.compile("^(.*),\\d\\d\\d WARN \\[net\\.ttddyy\\.dsproxy\\.listener\\.CommonsQueryLoggingListener] - ;(\\d+) ;.*; \\[(.*)\\] ;(.*)$");
	private Session session;
	private String typeName = "CommonsQueryLoggingListener";
	private Map<String, ETDOperation> operations = new HashMap<String, ETDOperation>();
	private ETDType type;

	public ETDCommonsQueryLoggingListenerParseHandler(Session session) {
		this.session = session;
		this.initType();
		this.initOperations();
	}

	@SuppressWarnings("unchecked")
	private void initType() {
		Query query = this.session.createQuery("from ETDType where name = ?");
		query.setString(0, this.typeName);

		this.session.beginTransaction();
		List<ETDType> types = (List<ETDType>) query.list();
		this.session.getTransaction().commit();

		if (types.size() == 0) {
			ETDType type = new ETDType();
			type.setName(this.typeName);
			this.session.beginTransaction();
			this.session.save(type);
			this.session.getTransaction().commit();

			this.session.beginTransaction();
			types = (List<ETDType>) query.list();
			this.session.getTransaction().commit();

			this.type = types.get(0);
		} else {
			this.type = types.get(0);
		}
	}
	
	@SuppressWarnings("unchecked")
	private void initOperations() {
		Query query = this.session.createQuery("from ETDOperation");
		this.session.beginTransaction();
		List<ETDOperation> operations = (List<ETDOperation>) query.list();
		this.session.getTransaction().commit();
		
		for (ETDOperation operation : operations) {
			this.operations.put(operation.getName().toString(), operation);
		}
	}
	
	private void addOperation(ETDOperation operation) {
		this.session.beginTransaction();
		this.session.save(operation);
		this.session.getTransaction().commit();
		this.operations.put(operation.getName().toString(), operation);
	}
	
	private ETDOperation getOperation(String operationName) {
		return this.operations.get(operationName);
	}

	private void addLog(ETDLog log) {
		this.session.beginTransaction();
		this.session.save(log);
		this.session.getTransaction().commit();
	}
	
	public void handle(String string) {
		Matcher matcher = pattern.matcher(string);
		if (matcher.matches()) {
			String executed = matcher.group(1);
			long duration = (long) Integer.parseInt(matcher.group(2));
			byte[] operationName = matcher.group(3).getBytes();
			//int operationNameLength = 500;
			//if (operationName.length() > operationNameLength) {
			//	operationName = operationName.substring(0, operationNameLength);
			//}
			byte[] params = matcher.group(4).getBytes();
			//int paramsLength = 500;
			//if (params.length() > paramsLength) {
			//	params = params.substring(0, paramsLength);
			//}

			if (duration > 10000) {
				ETDOperation operation = this.getOperation(operationName.toString());
				if (operation == null) {
					operation = new ETDOperation();
					operation.setName(operationName);
					operation.setType(this.type);
					this.addOperation(operation);
				}
				
				ETDLog log = new ETDLog();
				log.setDuration(duration);
				log.setOperation(operation);
				log.setParams(params);

				try {
					log.setExecuted(new Timestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(executed).getTime()));
				} catch (ParseException e) {
					e.printStackTrace();
				}
				
				this.addLog(log);
			}
		}
	}

}
